package it.niedermann.android.markdown.markwon.textwatcher

import android.text.Editable
import android.text.TextWatcher
import io.noties.markwon.base.editor.MarkwonEditor
import io.noties.markwon.base.editor.MarkwonEditorTextWatcher
import io.noties.markwon.base.editor.MarkwonEditorTextWatcher.Companion.withPreRender
import it.niedermann.android.markdown.markwon.MarkwonMarkdownEditor
import java.util.concurrent.Executors

class CombinedTextWatcher(editor: MarkwonEditor, editText: MarkwonMarkdownEditor) :
    HashMap<Class<*>?, TextWatcher?>(), TextWatcher {
    private val watcher: TextWatcher

    init {
        put(
            MarkwonEditorTextWatcher::class.java,
            withPreRender(editor, Executors.newSingleThreadExecutor(), editText)
        )
        put(
            AutoContinuationTextWatcher::class.java, AutoContinuationTextWatcher(
                get<MarkwonEditorTextWatcher>(
                    MarkwonEditorTextWatcher::class.java
                )!!, editText
            )
        )
        put(
            LowerIndentionTextWatcher::class.java, LowerIndentionTextWatcher(
                get<AutoContinuationTextWatcher>(
                    AutoContinuationTextWatcher::class.java
                )!!, editText
            )
        )
        put(
            SearchHighlightTextWatcher::class.java, SearchHighlightTextWatcher(
                get<LowerIndentionTextWatcher>(
                    LowerIndentionTextWatcher::class.java
                )!!, editText
            )
        )
        watcher = get<SearchHighlightTextWatcher>(SearchHighlightTextWatcher::class.java)!!
    }

    operator fun <T> get(key: Class<T>?): T? {
        return super.get(key) as T?
    }

    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
        watcher.beforeTextChanged(s, start, count, after)
    }

    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
        watcher.onTextChanged(s, start, before, count)
    }

    override fun afterTextChanged(s: Editable) {
        watcher.afterTextChanged(s)
    }
}